export default class Coordinate {
  constructor(x, y, boardSize, bw) {
    this.x = x;
    this.y = y;
    this.boardSize = boardSize;
    this.bw = bw;
    this._near = null;
    this._slantNear = null;
    
    // 方向常量
    this._up = 0;
    this._down = 1;
    this._right = 2;
    this._left = 3;
  }

  up() {
    const c = new Coordinate(this.x, this.y - 1, this.boardSize,0);
    return c.isValid() ? c : null;
  }

  down() {
    const c = new Coordinate(this.x, this.y + 1, this.boardSize,0);
    return c.isValid() ? c : null;
  }

  right() {
    const c = new Coordinate(this.x + 1, this.y, this.boardSize,0);
    return c.isValid() ? c : null;
  }

  left() {
    const c = new Coordinate(this.x - 1, this.y, this.boardSize,0);
    return c.isValid() ? c : null;
  }

  leftUp() {
    const c = new Coordinate(this.x - 1, this.y - 1, this.boardSize);
    return c.isValid() ? c : null;
  }

  rightUp() {
    const c = new Coordinate(this.x + 1, this.y - 1, this.boardSize);
    return c.isValid() ? c : null;
  }

  rightDown() {
    const c = new Coordinate(this.x - 1, this.y - 1, this.boardSize);
    return c.isValid() ? c : null;
  }

  leftDown() {
    const c = new Coordinate(this.x - 1, this.y + 1, this.boardSize);
    return c.isValid() ? c : null;
  }

  initNear() {
    if (!this._near) {
      this._near = new Array(4).fill(null);
      this._near[this._up] = this.up();
      this._near[this._down] = this.down();
      this._near[this._right] = this.right();
      this._near[this._left] = this.left();
    }
  }

  initSlantNear() {
    if (!this._slantNear) {
      this._slantNear = new Array(4).fill(null);
      this._slantNear[this._up] = this.leftUp();
      this._slantNear[this._down] = this.rightUp();
      this._slantNear[this._right] = this.rightDown();
      this._slantNear[this._left] = this.leftDown();
    }
  }

  getNear(direction) {
    this.initNear();
    return this._near ? this._near[direction] : null;
  }

  getSlantNear(direction) {
    this.initSlantNear();
    return this._slantNear ? this._slantNear[direction] : null;
  }

  isValid() {
    if (this.x === 0 && this.y === 0) return true;
    if (this.x < 1) return false;
    if (this.y < 1) return false;
    if (this.x > this.boardSize) return false;
    if (this.y > this.boardSize) return false;
    return true;
  }

  equals(other) {
    return this === other || 
           (other instanceof Coordinate &&
            this.x === other.x &&
            this.y === other.y);
  }

  hashCode() {
    return this.x ^ this.y ^ this.bw;
  }
}
